package service

import (
	"context"
	"crypto/md5"
	"encoding/hex"
	"engine/dto"
	"engine/model"
	"fmt"
	"github.com/goccy/go-json"
	"github.com/hibiken/asynq"
	"io/ioutil"
	"lib/db"
	"lib/log"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"time"
)

type respData struct {
	Msg     string `json:"msg"`
	Success bool   `json:"success"`
	Code    int    `json:"code"`
	Data    struct {
		OrderNo string      `json:"orderNo"`
		Info    []*respInfo `json:"info"`
	} `json:"data"`
}

type respInfo struct {
	CpCode                   string                          `json:"cpCode"`
	TheLastTime              string                          `json:"theLastTime"`
	MailNo                   string                          `json:"mailNo"`
	TheLastMessage           string                          `json:"theLastMessage"`
	CpMobile                 string                          `json:"cpMobile"`
	LogisticsCompanyName     string                          `json:"logisticsCompanyName"`
	CpUrl                    string                          `json:"cpUrl"`
	TakeTime                 string                          `json:"takeTime"`
	Courier                  string                          `json:"courier"`
	CourierPhone             string                          `json:"courierPhone"`
	LogisticsStatusDesc      string                          `json:"logisticsStatusDesc"`
	LogisticsTraceDetailList []*respLogisticsTraceDetailList `json:"logisticsTraceDetailList"`
	LogisticsStatus          string                          `json:"logisticsStatus"`
}
type respLogisticsTraceDetailList struct {
	AreaCode           string `json:"areaCode,omitempty"`
	AreaName           string `json:"areaName,omitempty"`
	SubLogisticsStatus string `json:"subLogisticsStatus"`
	Time               int64  `json:"time"`
	LogisticsStatus    string `json:"logisticsStatus"`
	Desc               string `json:"desc"`
}

type emsTask struct {
	Oid int64 `json:"user_id"`
}

func generateSign(appid string, timestamp int64, appSecurity string) string {
	str := fmt.Sprintf("%s&%d&%s", appid, timestamp, appSecurity)
	hasher := md5.New()
	hasher.Write([]byte(str))
	return hex.EncodeToString(hasher.Sum(nil))
}

func sendRequest(expressNumber, mobile string) (*respData, error) {

	appid := "CWM950npHtfOa7sBqBbfGI84UVCbp5JF"
	appSecurity := "JLuQceOT1pql23KLROoni83VMsy7JupM"

	// 生成签名
	timestamp := time.Now().UnixNano() / 1e6 // 毫秒时间戳
	sign := generateSign(appid, timestamp, appSecurity)

	// 构建请求URL和参数
	apiUrl := "https://api.shumaidata.com/v4/express3/query"
	params := url.Values{}
	params.Add("appid", appid)
	params.Add("timestamp", strconv.FormatInt(timestamp, 10))
	params.Add("sign", sign)
	params.Add("number", expressNumber)

	if mobile != "" {
		params.Add("mobile", mobile)
	}

	// 发送GET请求
	fullUrl := fmt.Sprintf("%s?%s", apiUrl, params.Encode())
	resp, err := http.Get(fullUrl)
	if err != nil {
		log.Errorf("请求失败 SendRequest http.Get(fullUrl) %s %s %v", expressNumber, mobile, err)
		return nil, err
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取响应失败:", err)
		log.Errorf("请求失败 SendRequest ioutil.ReadAll(resp.Body) %s %s %v", expressNumber, mobile, err)
		return nil, err
	}
	var resps respData
	jsonErr := json.Unmarshal(body, &resps)
	if jsonErr != nil {
		log.Errorf("请求失败 SendRequest json.Unmarshal(body, &resp) %s %s %v", expressNumber, mobile, err)
		return nil, err
	}
	return &resps, nil
}
func HandleEmsTask(ctx context.Context, t *asynq.Task) error {

	var p emsTask
	err := json.Unmarshal(t.Payload(), &p)
	if err != nil {
		return fmt.Errorf("json.Unmarshal failed: %v: %w", err, asynq.SkipRetry)
	}
	var newOrder model.My_proorder
	err = db.GetDb().Select("id", "ems", "ems_no", "tel").Where("id=? and status>1", p.Oid).First(&newOrder).Error
	if err != nil || newOrder.Id == 0 {
		log.Errorf("HandleEmsTask  get order failed: %v. %s", err, p.Oid)
		return err
	}
	resp, err := sendRequest(newOrder.EmsNo, newOrder.Tel)
	if err != nil {
		return err
	}
	if resp.Code != 200 {
		log.Errorf("HandleEmsTask SendRequest failed: %v. %s", err, resp.Msg)
		return fmt.Errorf("SendRequest failed: %v. %s", err, resp.Msg)
	}

	if len(resp.Data.Info) > 0 {
		info := resp.Data.Info[0]
		var orderAddress model.My_order_address
		db.GetDb().Table("").Debug().Where("oid=?", p.Oid).First(&orderAddress)

		newOrder.FhStatus = info.LogisticsStatusDesc
		if info.LogisticsStatus == "SIGN" || info.LogisticsStatus == "AGENT_SIGN" {
			newOrder.Status = 3
		}

		orderAddress.Status = info.LogisticsStatus

		if len(info.LogisticsTraceDetailList) > 0 {
			extenInfo := make([]*model.My_order_address_ExtenInfo, 0, len(info.LogisticsTraceDetailList))
			for _, list := range info.LogisticsTraceDetailList {

				// 转换为 time.Time
				seconds := list.Time / 1000       // 秒部分
				nanos := (list.Time % 1000) * 1e6 // 剩余毫秒转为纳秒
				nowT := time.Unix(seconds, nanos)

				sm := ""
				switch list.SubLogisticsStatus {
				case "STA_INBOUND":
					sm = "已到达"
				case "WAIT_ACCEPT":
					sm = "待揽收"
				case "ACCEPT":
					sm = "已揽收"
				case "TRANSPORT":
					sm = "运输中"
				case "DELIVERING":
					sm = "派送中"
				case "AGENT_SIGN":
					sm = "已代签收"
				case "SIGN":
					sm = "已签收"
				case "FAILED":
					sm = "包裹异常"

				}

				extenInfo = append(extenInfo, &model.My_order_address_ExtenInfo{
					Dates:  &nowT,
					Desc:   list.Desc,
					Status: sm,
				})
			}

			sort.Slice(extenInfo[:], func(i, j int) bool {
				return i > j
			})
			orderExtenInfoJson, err := json.Marshal(extenInfo)
			if err != nil {
				log.Errorf("HandleEmsTask orderExtenInfoJson, err := json.Marshal(orderExtenInfo) %s %v", p.Oid, err)
				return err
			}

			orderAddress.ExtenInfo = orderExtenInfoJson
		}

		if orderAddress.Oid == 0 {
			orderAddress.Ems = newOrder.Ems
			orderAddress.EmsNo = newOrder.EmsNo
			orderAddress.Oid = p.Oid
			if err = dto.Create(&orderAddress); err != nil {
				log.Errorf("HandleEmsTask  dto.Create(&orderAddress) failed: %v. %s", err, p.Oid)
				return err
			}
		} else {
			if err = db.GetDb().Where("oid=?", orderAddress.Oid).Updates(&orderAddress).Error; err != nil {
				log.Errorf("HandleEmsTask  dto.Create(&orderAddress) failed: %v. %s", err, p.Oid)
				return err
			}
		}

	}

	return nil
}
